package com.elitesland.org.service.impl;

import cn.hutool.core.util.StrUtil;
import com.elitesland.core.base.PagingVO;
import com.elitesland.core.exception.BusinessException;
import com.elitesland.org.convert.OrgPostConvert;
import com.elitesland.org.entity.QOrgPostDO;
import com.elitesland.org.param.OrgPostQParam;
import com.elitesland.org.repo.OrgPostRepo;
import com.elitesland.org.service.OrgPostService;
import com.elitesland.org.vo.OrgPostVO;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class OrgPostServiceImpl implements OrgPostService {

    private OrgPostRepo orgPostRepo;

    @Autowired
    public void setOrgPostRepo(OrgPostRepo orgPostRepo) {
        this.orgPostRepo = orgPostRepo;
    }

    private final QOrgPostDO posts = QOrgPostDO.orgPostDO;

    @Override
    public PagingVO<OrgPostVO> search(OrgPostQParam param) {
        Predicate predicate = posts.isNull().or(posts.isNotNull());

        predicate = StrUtil.isBlank(param.getPostCode()) ? predicate :
                ExpressionUtils.and(predicate, posts.postCode.like("%" + param.getPostCode() + "%"));
        predicate = StrUtil.isBlank(param.getPostName()) ? predicate :
                ExpressionUtils.and(predicate, posts.postName.like("%" + param.getPostName() + "%"));
        predicate = param.getPostWeightS() == null ? predicate :
                ExpressionUtils.and(predicate, posts.postWeight.goe(param.getPostWeightS()));
        predicate = param.getPostWeightE() == null ? predicate :
                ExpressionUtils.and(predicate, posts.postWeight.loe(param.getPostWeightE()));

        val ret = orgPostRepo.findAll(predicate, param.getPageRequest());

        return PagingVO.<OrgPostVO>builder()
                .total(ret.getTotalElements())
                .records(ret.getContent().stream().map(OrgPostConvert.INSTANCE::doToVO)
                        .collect(Collectors.toList()))
                .build();
    }

    @Override
    public List<OrgPostVO> listAll() {
        return orgPostRepo.findAllByOrderByPostName().stream().map(OrgPostConvert.INSTANCE::doToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<OrgPostVO> listByIds(List<Long> ids) {
        return orgPostRepo.findAllByIdIn(ids).stream().map(OrgPostConvert.INSTANCE::doToVO)
                .collect(Collectors.toList());
    }

    @Override
    public Optional<OrgPostVO> oneById(Long id) {
        return orgPostRepo.findById(id).map(OrgPostConvert.INSTANCE::doToVO);
    }

    @Override
    public Optional<OrgPostVO> oneByCode(String code) {
        return orgPostRepo.findByPostCode(code).map(OrgPostConvert.INSTANCE::doToVO);
    }

    @Override
    @Transactional(rollbackOn = {Exception.class})
    public Long create(OrgPostVO post) {
        val postOpt = oneByCode(post.getPostCode());
        if (postOpt.isPresent()) {
            throw new BusinessException("岗位编码：" + post.getPostCode() + ", 已存在");
        }
        val newPost = orgPostRepo.save(OrgPostConvert.INSTANCE.voToDO(post));

        return newPost.getId();
    }

    @Override
    @Transactional(rollbackOn = {Exception.class})
    public void update(OrgPostVO post) {
        orgPostRepo.findByIdNotAndPostCode(post.getId(), post.getPostCode()).ifPresentOrElse(
                p -> {
                    throw new BusinessException("岗位编码:" + post.getPostCode() + ", 已经被使用");
                },
                () -> {
                    orgPostRepo.save(OrgPostConvert.INSTANCE.voToDO(post));
                }
        );
    }

    @Override
    @Transactional(rollbackOn = {Exception.class})
    public void removeByIds(List<Long> ids) {
        orgPostRepo.deleteAllByIdIn(ids);
    }
}
